package com.whfc.fse.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.whfc.common.enums.BindFlag;
import com.whfc.common.enums.NetState;
import com.whfc.common.exception.BizException;
import com.whfc.common.result.ListData;
import com.whfc.common.result.PageData;
import com.whfc.common.result.ResultEnum;
import com.whfc.common.util.DateUtil;
import com.whfc.common.util.PageUtil;
import com.whfc.fse.dao.FseCrawlerDataMapper;
import com.whfc.fse.dao.FseCrawlerMapper;
import com.whfc.fse.dto.*;
import com.whfc.fse.entity.FseCrawler;
import com.whfc.fse.entity.FseCrawlerData;
import com.whfc.fse.param.*;
import com.whfc.fse.service.FseCrawlerService;
import com.whfc.influx.dao.FseCrawlerDataLogDao;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author qzexing
 * @version 1.0
 * @date 2021/10/30 17:28
 */
@DubboService(interfaceClass = FseCrawlerService.class, version = "1.0.0")
public class FseCrawlerServiceImpl implements FseCrawlerService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private FseCrawlerMapper fseCrawlerMapper;

    @Autowired
    private FseCrawlerDataMapper fseCrawlerDataMapper;

    @Autowired
    private FseCrawlerDataLogDao fseCrawlerDataLogDao;

    @Override
    public PageData<FseCrawlerDTO> list(Integer pageNum, Integer pageSize, Integer deptId, String keyword, Integer bindFlag,
                                        Integer netState) throws BizException {
        logger.info("获取履带吊列表, pageNum:{}, pageSize:{}, deptId:{}, keyword:{}, bindFlag:{}, netState:{}",
                pageNum, pageSize, deptId, keyword, bindFlag, netState);
        PageHelper.startPage(pageNum, pageSize);
        List<FseCrawlerDTO> list = fseCrawlerMapper.selectCrawlerList(deptId, bindFlag, netState, keyword);
        PageHelper.clearPage();
        //设置操作手及监控信息
        for (FseCrawlerDTO fseCrawlerDTO : list) {
            setOperatorsAndFvsDevices(fseCrawlerDTO);
        }
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public ListData<FseCrawlerDTO> list(Integer deptId, Integer bindFlag, Integer netState) throws BizException {
        logger.info("获取履带吊列表, deptId:{}, bindFlag:{}, netState:{}", deptId, bindFlag, netState);
        List<FseCrawlerDTO> list = fseCrawlerMapper.selectCrawlerList(deptId, bindFlag, netState, null);
        //设置操作手及监控信息
        for (FseCrawlerDTO fseCrawlerDTO : list) {
            setOperatorsAndFvsDevices(fseCrawlerDTO);
        }
        return new ListData<>(list);
    }

    @Override
    public FseCrawlerDTO detail(Integer crawlerId) throws BizException {
        logger.info("获取履带吊详情, crawlerId:{}", crawlerId);
        FseCrawler fseCrawler = fseCrawlerMapper.selectByPrimaryKey(crawlerId);
        FseCrawlerDTO fseCrawlerDTO = new FseCrawlerDTO();
        BeanUtils.copyProperties(fseCrawler, fseCrawlerDTO);
        fseCrawlerDTO.setCrawlerId(fseCrawler.getId());
        //设置操作手及监控信息
        setOperatorsAndFvsDevices(fseCrawlerDTO);
        return fseCrawlerDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(FseCrawlerAddParam request) throws BizException {
        logger.info("新增履带吊, request:{}", request);
        String code = request.getCode();
        Integer deptId = request.getDeptId();
        FseCrawler fseCrawler = fseCrawlerMapper.selectByDeptIdAndCode(deptId, code);
        if (fseCrawler != null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "此设备编号已存在，不能重复添加");
        }
        fseCrawler = new FseCrawler();
        BeanUtils.copyProperties(request, fseCrawler);
        //设置操作手
        String operators = JSON.toJSONString(request.getOperatorList());
        fseCrawler.setOperators(operators);
        fseCrawlerMapper.insertSelective(fseCrawler);
        //初始化履带吊初始数据
        FseCrawlerData crawlerData = new FseCrawlerData();
        crawlerData.setCrawlerId(fseCrawler.getId());
        fseCrawlerDataMapper.insertSelective(crawlerData);
    }


    @Override
    public void edit(FseCrawlerEditParam request) throws BizException {
        logger.info("修改履带吊, request：{}", request);
        Integer crawlerId = request.getCrawlerId();
        FseCrawler fseCrawler = fseCrawlerMapper.selectByPrimaryKey(crawlerId);
        if (fseCrawler == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该履带吊不存在");
        }
        String code = request.getCode();
        Integer deptId = fseCrawler.getDeptId();
        FseCrawler fseCrawler1 = fseCrawlerMapper.selectByDeptIdAndCode(deptId, code);
        if (fseCrawler1 != null && !fseCrawler1.getId().equals(crawlerId)) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "此设备编号已存在，不能重复添加");
        }
        FseCrawler crawler = new FseCrawler();
        BeanUtils.copyProperties(request, crawler);
        crawler.setId(crawlerId);
        //设置操作手
        String operators = JSON.toJSONString(request.getOperatorList());
        crawler.setOperators(operators);
        fseCrawlerMapper.updateByPrimaryKeySelective(crawler);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void del(Integer crawlerId) throws BizException {
        logger.info("删除履带吊, crawlerId：{}", crawlerId);
        FseCrawler fseCrawler = fseCrawlerMapper.selectByPrimaryKey(crawlerId);
        if (fseCrawler == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该履带吊不存在");
        }
        if (BindFlag.BIND.getValue().equals(fseCrawler.getBindFlag())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该塔机已绑定硬件,不能删除");
        }
        fseCrawlerMapper.deleteLogicById(crawlerId);
        //删除履带吊数据
        fseCrawlerDataMapper.delByCrawlerId(crawlerId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBindState(FseCrawlerBindParam request) throws BizException {
        logger.info("更新履带吊绑定状态, request:{}", request);
        Integer crawlerId = request.getCrawlerId();
        FseCrawler fseCrawler = fseCrawlerMapper.selectByPrimaryKey(crawlerId);
        if (fseCrawler == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该履带吊不存在");
        }
        Integer bingStatus = request.getBingStatus();
        if (BindFlag.BIND.getValue().equals(bingStatus)) {
            //绑定
            if (BindFlag.BIND.getValue().equals(fseCrawler.getBindFlag())) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "该履带吊已绑定硬件");
            }
            String sn = request.getSn();
            String platform = request.getPlatform();
            FseCrawler crawler = fseCrawlerMapper.selectBySnAndPlatform(sn, platform);
            if (crawler != null) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "该硬件已被绑定");
            }
            //更新绑定状态
            fseCrawlerMapper.updateBindFlag(crawlerId, platform, bingStatus, sn, NetState.OFFLINE.getValue());
        } else {
            //解绑
            if (BindFlag.UNBIND.getValue().equals(fseCrawler.getBindFlag())) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "该履带吊未绑定硬件");
            }
            //更新绑定状态
            fseCrawlerMapper.updateBindFlag(crawlerId, null, bingStatus, null, NetState.OFFLINE.getValue());
        }
    }

    @Override
    public FseCrawlerDataDTO getLatest(Integer crawlerId) throws BizException {
        logger.info("获取履带吊最新数据, crawlerId:{}", crawlerId);
        FseCrawler fseCrawler = fseCrawlerMapper.selectByPrimaryKey(crawlerId);
        if (fseCrawler == null) {
            throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "该履带吊不存在.");
        }
        //防碰撞标记
        Integer collisionFlag = fseCrawler.getCollisionFlag();
        FseCrawlerDataDTO crawlerDataDTO = new FseCrawlerDataDTO();
        FseCrawlerData crawlerData = fseCrawlerDataMapper.selectByCrawlerId(crawlerId);
        if (crawlerData != null) {
            BeanUtils.copyProperties(crawlerData, crawlerDataDTO);
            if (1 == collisionFlag) {
                //获取防碰撞信息
                String probeDistances = crawlerData.getProbeDistances();
                if (StringUtils.isNotBlank(probeDistances)) {
                    List<Double> list = JSON.parseArray(probeDistances, Double.class);
                    crawlerDataDTO.setProbeDistanceList(list);
                }
                //处理防撞报警
                String probeDistanceWarns = crawlerData.getProbeDistanceWarns();
                if (StringUtils.isNotBlank(probeDistanceWarns)) {
                    List<Integer> list = JSON.parseArray(probeDistanceWarns, Integer.class);
                    int probeDistanceWarn = 0;
                    for (Integer i : list) {
                        probeDistanceWarn += i;
                    }
                    if (probeDistanceWarn > 0) {
                        probeDistanceWarn = 1;
                    } else {
                        probeDistanceWarn = 0;
                    }
                    crawlerDataDTO.setProbeDistanceWarn(probeDistanceWarn);
                }
            }
        }
        crawlerDataDTO.setCollisionFlag(collisionFlag);
        return crawlerDataDTO;
    }

    @Override
    public List<FseCrawlerDataLogDTO> getCrawlerLog(Integer crawlerId, Date date) throws BizException {
        logger.info("获取履带吊历史数据, crawlerId:{}, date:{}", crawlerId, date);
        Date startTime = DateUtil.getDateBegin(date);
        Date endTime = DateUtil.getDateEnd(date);
        return fseCrawlerDataLogDao.selectCrawlerDataLogListByCrawlerId(crawlerId, startTime, endTime);
    }

    @Override
    public List<FseCrawlerDataLogDTO> getCrawlerLog(Integer crawlerId, Date date, String field) throws BizException {
        logger.info("获取履带吊历史数据, crawlerId:{}, date:{},field:{}", crawlerId, date, field);
        Date startTime = DateUtil.getDateBegin(date);
        Date endTime = DateUtil.getDateEnd(date);
        String[] columns = StringUtils.isNotEmpty(field) ? new String[]{field} : null;
        return fseCrawlerDataLogDao.selectCrawlerDataSamplingByCrawlerId(crawlerId, startTime, endTime, columns);
    }

    @Override
    public List<FseFvsDeviceDTO> getFvsDeviceList(Integer crawlerId) throws BizException {
        logger.info("获取监控列表, crawlerId:{}", crawlerId);
        FseCrawler fseCrawler = fseCrawlerMapper.selectByPrimaryKey(crawlerId);
        if (fseCrawler == null) {
            throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "该履带吊不存在");
        }
        List<FseFvsDeviceDTO> list = new ArrayList<>();
        String fvsDevices = fseCrawler.getFvsDevices();
        if (StringUtils.isNotBlank(fvsDevices)) {
            return JSON.parseArray(fvsDevices, FseFvsDeviceDTO.class);
        }
        return list;
    }

    @Override
    public void bindFvs(FseFvsParam param) throws BizException {
        logger.info("绑定监控, param:{}", param);
        Integer fseId = param.getFseId();
        FseCrawler fseCrawler = fseCrawlerMapper.selectByPrimaryKey(fseId);
        if (fseCrawler == null) {
            throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "该履带吊不存在");
        }
        //绑定新的监控设备
        List<FseFvsDeviceParam> list = param.getFvsList();
        if (list == null) {
            list = new ArrayList<>();
        }
        String fvsDevices = JSON.toJSONString(list);
        fseCrawler.setFvsDevices(fvsDevices);
        fseCrawlerMapper.updateByPrimaryKeySelective(fseCrawler);
    }

    /**
     * 设置操作手及监控信息
     *
     * @param fseCrawler 塔机对象
     */
    public void setOperatorsAndFvsDevices(FseCrawlerDTO fseCrawler) {
        if (fseCrawler == null) {
            return;
        }
        //获取操作手
        String operators = fseCrawler.getOperators();
        if (StringUtils.isNotBlank(operators)) {
            List<FseOperatorDTO> operatorList = JSON.parseArray(operators, FseOperatorDTO.class);
            fseCrawler.setOperatorList(operatorList);
        }
        fseCrawler.setOperators(null);
        //获取监控
        String fvsDevices = fseCrawler.getFvsDevices();
        if (StringUtils.isNotBlank(fvsDevices)) {
            List<FseFvsDeviceDTO> fvsList = JSON.parseArray(fvsDevices, FseFvsDeviceDTO.class);
            fseCrawler.setFvsList(fvsList);
        }
        fseCrawler.setFvsDevices(null);
    }
}
